/**
    @author: ChenLin
    @date: 2022/11/11 todo 基础工具类
**/

package handler

import (
	"bytes"
	"encoding/json"
	"flamingo/utils"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"math/rand"
	"mime/multipart"
	"net/http"
	"os"
	"os/exec"
	"path"
	"reflect"
	"strconv"
	"strings"
	"time"
)

type ReqData struct {
	Opttype int `json:"opttype"`
	Data    struct {
		SystemName string   `json:"systemName"`
		Account    []string `json:"account"`
	} `json:"data"`
}

var ch chan Task

func NewChannel() *chan Task {
	if ch == nil {
		ch = make(chan Task, 2)
	}
	return &ch
}

func JsonReqRsp(w http.ResponseWriter, r *http.Request) {
	var reqdata ReqData
	// 调用json包的解析，解析请求body
	if err := json.NewDecoder(r.Body).Decode(&reqdata); err != nil {
		r.Body.Close()
		log.Println(err)
	}
	jsonStr, _ := json.Marshal(reqdata)
	log.Println("req json: ", string(jsonStr))

	// 返回json字符串给客户端
	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(reqdata)
}

/**
 * @Author ChenLin
 * @Description //TODO 命令行运行ffmpeg命令
 * @Date 14:34 2022/11/11
 **/

func RunFfmpegCmd(arg ...string) error {
	log.Println("ffmpeg ", arg)
	cmd := exec.Command("ffmpeg", arg...)
	var out bytes.Buffer
	var stderr bytes.Buffer
	cmd.Stdout = &out
	cmd.Stderr = &stderr
	if err := cmd.Start(); err != nil { // 运行命令
		log.Println(err.Error(), stderr.String())
		return err
	}
	if err := cmd.Wait(); err != nil {
		log.Println(err.Error(), stderr.String())
		return err
	}
	return nil
}

func ParseResponse(code int, msg string, result interface{}) Rep {
	req := Rep{
		Code:   code,
		Msg:    msg,
		Result: result,
	}
	return req
}

func ClientPost(url string, rep Rep) error {
	log.Println(url, rep)
	bytesData, err := json.Marshal(rep)
	if err != nil {
		log.Println("Marshal error:", err)
	}
	body := strings.NewReader(string(bytesData))
	httpReq, err := http.NewRequest("POST", url, body)
	if err != nil {
		log.Println("NewRequest error:", err)
	}
	httpReq.Header.Add("Content-Type", "application/json")
	httpRsp, err := http.DefaultClient.Do(httpReq)
	defer httpRsp.Body.Close()
	if err != nil {
		fmt.Println("Fatal error ", err.Error())
		return err
	}
	return nil
}

func RemoveFile(rep Rep) (err error) {
	var typeInfo = reflect.TypeOf(rep.Result)
	var valInfo = reflect.ValueOf(rep.Result)
	num := typeInfo.NumField()
	for i := 0; i < num; i++ {
		key := typeInfo.Field(i).Name
		val := valInfo.Field(i).Interface()
		log.Println("Remove file :", key, val)
		if (key == "ScreenUrl" || key == "CompressUrl" || key == "DownloadUrl") && val != "" {
			err = os.Remove(val.(string))
			if err != nil {
				log.Println("Remove fail :", err)
			}
		}
	}
	return
}

func DownloadVideoByFileFrom(file multipart.File, dirUrl string) (string, error) {
	b, err := ioutil.ReadAll(file)
	if err != nil {
		log.Println("DownloadVideoByFileFrom ReadAll：", err)
		return "", err
	}
	fileName := path.Base(utils.MD5(time.Now().String()+strconv.Itoa(rand.Int()))) + ".mp4"
	err = ioutil.WriteFile(dirUrl+fileName, b, 0777)
	if err != nil {
		log.Println("DownloadVideoByFileFrom WriteFile err:", err)
		return "", err
	}
	return fmt.Sprintf("%s%s", dirUrl, fileName), nil
}

func DownloadVideoByBytes(read io.ReadCloser, dirUrl string) (string, error) {
	fileName := path.Base(utils.MD5(time.Now().String()+strconv.Itoa(rand.Int()))) + ".mp4"
	file, err := os.OpenFile(dirUrl+fileName, os.O_WRONLY|os.O_CREATE, 0777)
	defer file.Close()
	_, err = io.Copy(file, read)
	if err != nil {
		log.Println("DownloadVideoByBytes Copy err:", err)
		return "", err
	}
	return fmt.Sprintf("%s%s", dirUrl, fileName), nil
}
